﻿#include "GraphDataCalculate.h"

#include "FITK_Kernel/FITKCore/FITKDataRepo.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoSketch2D.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoDatum.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsVirtualTopo.h"
#include "FITK_Component/FITKGeoCompOCC/FITKOCCVirtualTopoCreator.h"
#include "FITK_Component/FITKGeoCompOCC/FITKAbstractOCCModel.h"

#include <Standard_Handle.hxx>
#include <AIS_InteractiveContext.hxx>
#include <V3d_View.hxx>
#include <TopoDS_Shape.hxx>
#include <AIS_ColoredShape.hxx>
#include <BRepPrimAPI_MakeCylinder.hxx>
#include <BRepPrimAPI_MakeCone.hxx>
#include <TopoDS.hxx>
#include <BRepBndLib.hxx>
#include <BRepGProp_Face.hxx>
#include <GProp_GProps.hxx>
#include <BRepGProp.hxx>
#include <cmath>

namespace GraphData
{
    void GraphDataCalculate::calculateOCCGeoCenter(int virTopoId, double * pos)
    {
        Interface::FITKAbsVirtualTopo* vTopo = FITKDATAREPO->getTDataByID<Interface::FITKAbsVirtualTopo>(virTopoId);
        if (vTopo == nullptr){
            return;
        }

        //获取形状
        OCC::FITKOCCTopoShape* occVTopo = vTopo->getShapeT<OCC::FITKOCCTopoShape>();
        if (occVTopo == nullptr){
            return;
        }

        //获取OCC形状
        TopoDS_Shape shape = occVTopo->getTopoShape();

        //中心点计算
        gp_Pnt center;
        gp_Vec dir;

        TopAbs_ShapeEnum st = shape.ShapeType();
        switch (st) {
        case TopAbs_ShapeEnum::TopAbs_FACE:
        {
            // Cast to the face shape.
            TopoDS_Face & face = TopoDS::Face(shape);

            // Get the mid point and normal.( on the mid point )
            BRepGProp_Face bf(face);
            double uMin, uMax, vMin, vMax;
            bf.Bounds(uMin, uMax, vMin, vMax);
            double midU = (uMin + uMax) / 2;
            double midV = (vMin + vMax) / 2;
            bf.Normal(midU, midV, center, dir);

            break;
        }
        case TopAbs_ShapeEnum::TopAbs_EDGE: {
            // Cast to the edge shape.
            TopoDS_Edge & edge = TopoDS::Edge(shape);

            // Cast to the geom curve.
            double first, last;
            Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, first, last);
            if (!curve)
            {
                return;
            }

            //获取中心点
            double centerPos = first + 0.5*(last - first);
            center = curve->Value(centerPos);
            break;
        }
        }

        pos[0] = center.X();
        pos[1] = center.Y();
        pos[2] = center.Z();
    }

    void GraphDataCalculate::calculateLineEndPoint(double * startPoint, double * direction, double distance, double * endPoint)
    {
        //计算x、y、z、模长角度
        double dirX = direction[0];
        double dirY = direction[1];
        double dirZ = direction[2];
        double dirL = std::sqrt(dirX*dirX + dirY * dirY + dirZ * dirZ);

        //向量归一化（单位向量）
        double dirUnit[3] = { dirX / dirL,dirY / dirL ,dirZ / dirL };

        //计算单位向量移动后的点
        double dirPoint[3] = { dirUnit[0] * distance,dirUnit[1] * distance ,dirUnit[2] * distance };

        //终点 = 起始点+单位向量移动后的点
        endPoint[0] = startPoint[0] + dirPoint[0];
        endPoint[1] = startPoint[1] + dirPoint[1];
        endPoint[2] = startPoint[2] + dirPoint[2];
    }
}